package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"fmt"
	"github.com/shopspring/decimal"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"strings"
	"time"
)

type ShopTrafficSrv struct{}

func (s *ShopTrafficSrv) FirstTrafficTrend(req request.ShopFirstTrafficTrend) response.Resp {
	filter := bson.D{{"shop_id", req.ShopId}}
	if req.DateVal != "" {
		if req.DateType == 1 || req.DateType == 4 { // 日期
			dateVal, _ := time.Parse("2006-01-02", req.DateVal)
			sDate := dateVal.AddDate(0, 0, -7)
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sDate, "$lte": dateVal}})
		} else if req.DateType == 2 || req.DateType == 3 { // 近7天or近30天
			dateRange := strings.Split(req.DateVal, "~")
			sDate, _ := time.Parse("2006-01-02", dateRange[0])
			eDate, _ := time.Parse("2006-01-02", dateRange[1])
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sDate, "$lte": eDate}})
		} else if req.DateType == 5 { // 月份
			month, _ := time.Parse("2006-01", req.DateVal)
			sd := util.GetMonthStartAndEnd(month.Year(), int(month.Month()))
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sd["start"], "$lte": sd["end"]}})
		}
	}

	match := bson.D{{"$match", filter}}
	unwind := bson.D{
		{"$unwind", "$first_traffic_trend"},
	}
	group := bson.D{{
		"$group", bson.D{
			{"_id", bson.D{
				{"shop_id", bson.M{"$toInt": "$shop_id"}},
				{"date", "$date"},
				{"source_id", bson.M{"$toInt": "$first_traffic_trend.source_id"}},
			}},
			{"val", bson.M{"$sum": bson.M{"$toInt": "$first_traffic_trend.ctm_item_click_uv"}}},
		},
	}}
	lookup := bson.D{{
		"$lookup", bson.M{
			"from":         "traffic_meta",
			"localField":   "_id.source_id",
			"foreignField": "sourceId",
			"as":           "source",
		},
	}}
	sourceUnwind := bson.D{
		{"$unwind", "$source"},
	}
	finalProject := bson.D{{
		"$project", bson.D{
			{"_id", 1},
			{"name", "$source.name"},
			{"val", 1},
		},
	}}
	sort := bson.D{{"$sort", bson.D{{"_id.date", 1}}}}
	cursor, err := global.MongoDB.Collection("shop_traffic").Aggregate(context.TODO(), mongo.Pipeline{match, unwind, group, lookup, sourceUnwind, finalProject, sort})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error()).SetMsg(err.Error())
	}
	var result []model.ShopFirstTrafficTrend
	if err = cursor.All(context.TODO(), &result); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if len(result) == 0 {
		return response.OK
	}

	resp := make(map[string][]model.ShopFirstTrafficTrend)
	for _, res := range result {
		resp[res.Name] = append(resp[res.Name], res)
	}
	return response.OK.WithData(resp)
}

func (s *ShopTrafficSrv) SecondTrafficRank(req request.ShopSecondTrafficRank) response.Resp {
	filter := bson.D{{"shop_id", req.ShopId}}
	if req.DateVal != "" {
		if req.DateType == 1 || req.DateType == 4 { // 日期
			dateVal, _ := time.Parse("2006-01-02", req.DateVal)
			filter = append(filter, bson.E{Key: "date", Value: dateVal})
		} else if req.DateType == 2 || req.DateType == 3 { // 近7天or近30天
			dateRange := strings.Split(req.DateVal, "~")
			sDate, _ := time.Parse("2006-01-02", dateRange[0])
			eDate, _ := time.Parse("2006-01-02", dateRange[1])
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sDate, "$lte": eDate}})
		} else if req.DateType == 5 { // 月份
			month, _ := time.Parse("2006-01", req.DateVal)
			sd := util.GetMonthStartAndEnd(month.Year(), int(month.Month()))
			filter = append(filter, bson.E{Key: "date", Value: bson.M{"$gte": sd["start"], "$lte": sd["end"]}})
		}
	}

	match := bson.D{{"$match", filter}}
	unwind := bson.D{
		{"$unwind", "$second_traffic_rank"},
	}
	group := bson.D{{
		"$group", bson.D{
			{"_id", bson.D{
				{"shop_id", bson.M{"$toInt": "$shop_id"}},
				{"source_id", bson.M{"$toInt": "$second_traffic_rank.source_id"}},
			}},
			{"ctm_item_click_uv", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.ctm_item_click_uv"}}},
			{"item_order_cnt", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.item_order_cnt"}}},
			{"order_uv", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.order_uv"}}},
			{"item_cart_uv", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.item_cart_uv"}}},
			{"ctm_item_click_pv", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.ctm_item_click_pv"}}},
			{"item_cart_pv", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.item_cart_pv"}}},
			{"item_order_usd", bson.M{"$sum": bson.M{"$toDouble": "$second_traffic_rank.item_order_usd"}}},
			{"item_cart_cnt", bson.M{"$sum": bson.M{"$toInt": "$second_traffic_rank.item_cart_cnt"}}},
		},
	}}
	lookup := bson.D{{
		"$lookup", bson.M{
			"from":         "traffic_meta",
			"localField":   "_id.source_id",
			"foreignField": "sourceId",
			"as":           "source",
		},
	}}
	sourceUnwind := bson.D{
		{"$unwind", "$source"},
	}
	sort := bson.D{{"$sort", bson.D{{"ctm_item_click_uv", -1}}}}
	cursor, err := global.MongoDB.Collection("shop_traffic").Aggregate(context.TODO(), mongo.Pipeline{match, unwind, group, lookup, sort, sourceUnwind})
	if err != nil {
		fmt.Println(err)
		return response.ErrQuery.SetMsg(err.Error())
	}
	var result []model.ShopSecondTrafficRank
	if err = cursor.All(context.TODO(), &result); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	for i, str := range result {
		if str.CtmItemClickUv != 0 {
			a := decimal.NewFromInt(int64(str.OrderUv))
			b := decimal.NewFromInt(int64(str.CtmItemClickUv))
			result[i].CtmOrderViewRate = a.Div(b)
		}
	}
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error()).SetMsg(err.Error())
	}
	return response.OK.WithData(result)

}
